<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Cache integration</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="mysqlnd-ms.gtid.html">Global transaction IDs</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="mysqlnd-ms.supportedclusters.html">Supported clusters</a></div>
 <div class="up"><a href="mysqlnd-ms.concepts.html">Concepts</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="mysqlnd-ms.concept_cache" class="section">
  <h2 class="title">Cache integration</h2>
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <strong>Version requirement</strong><br />
   <p class="para">
    The feature requires use of PECL/mysqlnd_ms 1.3.0-beta or later,
    and PECL/mysqlnd_qc 1.1.0-alpha or newer. PECL/mysqlnd_ms must be
    compiled to support the feature. PHP 5.4.0 or newer is required.
   </p>
  </p></blockquote>
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <strong>Setup: extension load order</strong><br />
   <p class="para">
    PECL/mysqlnd_ms must be loaded before PECL/mysqlnd_qc, when using shared
    extensions.
   </p>
  </p></blockquote>
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <strong>Feature stability</strong><br />
   <p class="para">
    The cache integration is of beta quality.
   </p>
  </p></blockquote>
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <strong>Suitable MySQL clusters</strong><br />
   <p class="para">
    The feature is targeted for use with MySQL Replication (primary copy).
    Currently, no other kinds of MySQL clusters are supported. Users
    of such cluster must control PECL/mysqlnd_qc manually if they are
    interested in client-side query caching.
   </p>
  </p></blockquote>
  <p class="para">
   Support for MySQL replication clusters (asynchronous primary copy) is the
   main focus of PECL/mysqlnd_ms. The slaves of a MySQL replication cluster
   may or may not reflect the latest updates from the master.
   Slaves are asynchronous and can lag behind the master. A read from a slave
   is eventual consistent from a cluster-wide perspective.
  </p>
  <p class="para">
   The same level of consistency is offered by a local cache using time-to-live (TTL)
   invalidation strategy. Current data or stale data may be served. Eventually, data
   searched for in the cache is not available and the source of the cache needs to
   be accessed.
  </p>
  <p class="para">
   Given that both a MySQL Replication slave (asynchronous secondary) and a local
   TTL-driven cache deliver the same level of service it is possible to transparently
   replace a remote database access with a local cache access to gain better possibility.
  </p>
  <p class="para">
   As of PECL/mysqlnd_ms 1.3.0-beta the plugin is capable of transparently controlling
   PECL/mysqlnd_ms 1.1.0-alpha or newer to cache a read-only query if explicitly
   allowed by setting an appropriate quality of service through
   <span class="function"><a href="function.mysqlnd-ms-set-qos.html" class="function">mysqlnd_ms_set_qos()</a></span>. Please, see the
   <a href="mysqlnd-ms.quickstart.cache.html" class="link">quickstart</a> for a code example.
   Both plugins must be installed, PECL/mysqlnd_ms must be compiled to support the
   cache feature and PHP 5.4.0 or newer has to be used.
  </p>
  <p class="para">
   Applications have full control of cache usage and can request fresh data
   at any time, if need be. Thec ache usage can be enabled and disabled
   time during the execution of a script. The cache will be used
   if <span class="function"><a href="function.mysqlnd-ms-set-qos.html" class="function">mysqlnd_ms_set_qos()</a></span> sets the quality of service
   to eventual consistency and enables cache usage. Cache usage is disabled by
   requesting higher consistency levels, for example,
   session consistency (read your writes). Once the quality of service has been
   relaxed to eventual consistency the cache can be used again.
  </p>
  <p class="para">
   If caching is enabled for a read-only statement, PECL/mysqlnd_ms may inject
   <a href="mysqlnd-qc.quickstart.caching.html" class="link">SQL hints to control caching</a>
   by PECL/mysqlnd_qc. It may modify the SQL statement it got from the application.
   Subsequent SQL processors are supposed to ignore the SQL hints. A SQL hint is a
   SQL comment. Comments must not be ignored, for example, by the database server.
  </p>
  <p class="para">
   The TTL of a cache entry is computed on a per statement basis. Applications
   set an maximum age for the data they want to retrieve using
   <span class="function"><a href="function.mysqlnd-ms-set-qos.html" class="function">mysqlnd_ms_set_qos()</a></span>. The age sets an approximate upper limit
   of how many seconds the data returned may lag behind the master.
  </p>
  <p class="para">
   The following logic is used to compute the actual TTL if caching is enabled.
   The logic takes the estimated slave lag into account for choosing a TTL. If,
   for example, there are two slaves lagging 5 and 10 seconds behind and the maximum
   age allowed is 60 seconds, the TTL is set to 50 seconds. Please note, the
   age setting is no more than an estimated guess.
   <ul class="itemizedlist">
    <li class="listitem">
     <span class="simpara">
      Check whether the statement is read-only. If not, don&#039;t cache.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      If caching is enabled, check the slave lag of all configured slaves.
      Establish slave connections if none exist so far and lazy connections are
      used.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      Send <em>SHOW SLAVE STATUS</em> to all slaves. Do not wait
      for the first slave to reply before sending to the second slave. Clients
      often wait long for replies, thus we send out all requests in a burst before
      fetching in a second stage.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      Loop over all slaves. For every slave wait for its reply. Do not start
      checking another slave before the currently waited for slave has replied.
      Check for <em>Slave_IO_Running=Yes</em> and <em>Slave_SQL_Running=Yes</em>.
      If both conditions hold true, fetch the value of <em>Seconds_Behind_Master</em>.
      In case of any errors or if conditions fail, set an error on the slave connection.
      Skip any such slave connection for the rest of connection filtering.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      Search for the maximum value of <em>Seconds_Behind_Master</em> from
      all slaves that passed the previous conditions. Subtract the value from
      the maximum age provided by the user with <span class="function"><a href="function.mysqlnd-ms-set-qos.html" class="function">mysqlnd_ms_set_qos()</a></span>.
      Use the result as a TTL.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      The filtering may sort out all slaves. If so, the maximum age is used as
      TTL, because the maximum lag found equals zero. It is perfectly valid to
      sort out all slaves. In the following it is up to subsequent filter
      to decide what to do. The built-in load balancing filter will pick the
      master.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      Inject the appropriate SQL hints to enable caching by PECL/mysqlnd_qc.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      Proceed with the connection filtering, e.g. apply load balancing rules to
      pick a slave.
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      PECL/mysqlnd_qc is loaded after PECL/mysqlnd_ms by PHP. Thus, it will see
      all query modifications of PECL/mysqlnd_ms and cache the query if instructed
      to do so.
     </span>
    </li>
   </ul>
  </p>
  <p class="para">
   The algorithm may seem expensive. <em>SHOW SLAVE STATUS</em> is a very
   fast operation. Given a sufficient number of requests and cache hits per second the cost of
   checking the slaves lag can easily outweight the costs of the cache decision.
  </p>
  <p class="para">
   Suggestions on a better algorithm are always welcome.
  </p>
 </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="mysqlnd-ms.gtid.html">Global transaction IDs</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="mysqlnd-ms.supportedclusters.html">Supported clusters</a></div>
 <div class="up"><a href="mysqlnd-ms.concepts.html">Concepts</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>
